/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package eu.ict_omelette.mashup.compositionminer.util;

import eu.ict_omelette.mashup.canonicalmodel.CanonicalMashup;
import eu.ict_omelette.mashup.canonicalmodel.Component;
import eu.ict_omelette.mashup.canonicalmodel.Dataflow;
import eu.ict_omelette.mashup.canonicalmodel.InputPort;
import eu.ict_omelette.mashup.canonicalmodel.OutputPort;
import eu.ict_omelette.mashup.canonicalmodel.Port;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;

/**
 *
 * @author carlos
 */
public class Moss {
    LinkedList<CanonicalMashup> compRepo;
    double minSup;

    public Moss(LinkedList<CanonicalMashup> compRepo, double minSup){
        this.compRepo = compRepo;
        this.minSup = minSup * 100;
    }

    public LinkedList<CanonicalMashup> mine(){
        LinkedList<CanonicalMashup> patternList = new LinkedList();

        System.out.println("Now generating the input file for Moss...");
        String inFilePath = generateInputFile();

        //String[] cmd = {"/usr/bin/java",  "-Xmx1024M", "-cp moss.jar", "moss.Miner",
        //                "-inel", "-onel", "-s2", "-m4", filePath, "/tmp/vaca"};

        String outFilePath = "/tmp/moss-output" + System.currentTimeMillis();
        
        String[] cmd = {"/usr/bin/java",  "-Xmx1024M", "-cp", "moss.jar", "moss.Miner",
                        "-inel", "-onel", "-s" + minSup, "-m2", inFilePath, outFilePath};

        try{
            Process p = Runtime.getRuntime().exec(cmd);
            p.waitFor();            

            patternList = getPatternsFromFile(outFilePath);

        }catch(Exception e){
            e.printStackTrace();
        }

        return patternList;
    }

    public LinkedList<CanonicalMashup> getPatternsFromFile(String filePath) throws Exception{

        LinkedList<CanonicalMashup> patternList = new LinkedList();

        FileInputStream fsInputStream = new FileInputStream(filePath);
        DataInputStream in = new DataInputStream(fsInputStream);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String strLine;
        LinkedHashMap<Integer, Component> lhm = new LinkedHashMap();
        CanonicalMashup cm = new CanonicalMashup();
        int compId = 100;
        int dfId = -1;
        while ((strLine = br.readLine()) != null)   {
            if(strLine.trim().equals("")){
                //Util.printCanonicalMashup(cm);
                patternList.add(cm);
                cm = new CanonicalMashup();
                compId = 100;
                dfId = -1;
            }

            strLine = strLine.trim();
            String[] parts = strLine.split("\\s+");
            
            if(parts[0].equals("n")){
                Component c = new Component();
                c.setId("");
                if(parts[2].equals("loop")){
                    c.setIsEmbedding(Boolean.TRUE);
                }else{
                    c.setIsEmbedding(Boolean.FALSE);
                }
                c.setName(parts[2]);
                c.setType(parts[2]);
                compId++;
                c.setId("sw-" + compId);
                cm.addComponent(c);

                lhm.put(Integer.parseInt(parts[1]), c);
            }

            if(parts[0].equals("e")){
                Dataflow df = new Dataflow();                

                df.setId("");
                Integer fromInt = Integer.parseInt(parts[1]);
                Component fromComp = lhm.get(fromInt);

                
                Integer toInt = Integer.parseInt(parts[2]);
                Component toComp = lhm.get(toInt);

                String mapping = parts[3];
                String[] comps = mapping.split("=>");
                
                String[] pairLeft = comps[0].split("\\.");
                String[] pairRight = comps[1].split("\\.");

                OutputPort fromPort = new OutputPort();
                fromPort.setName(pairLeft[1]);

                InputPort toPort = new InputPort();
                toPort.setName(pairRight[1]);

                fromComp.addOutputPort(fromPort);
                toComp.addInputPort(toPort);

                df.setFromPort(fromComp, fromPort);
                df.setToPort(toComp, toPort);

                dfId++;
                df.setId("_w" + dfId);

                cm.addDataflow(df);
                 
            }

            
            
            
        }

        br.close();
        in.close();
        fsInputStream.close();

        return patternList;
        
    }

    public String generateInputFile(){
        String dirName = "/tmp/";
        String fileName = "moss-input" + System.currentTimeMillis();
        String filePath = dirName + fileName;

        try{
            FileWriter fstream = new FileWriter(filePath);
            BufferedWriter out = new BufferedWriter(fstream);

            int count = 0;
            Iterator <CanonicalMashup> itCm = compRepo.iterator();
            while(itCm.hasNext()){
                count ++;
                
                CanonicalMashup cm = itCm.next();

                out.write("% pipe-id: " + cm.getId() + "\n");

                LinkedHashMap<String, Integer> coIdx = new LinkedHashMap();
                LinkedHashMap<Integer, String> idxCo = new LinkedHashMap();
                Iterator<Component> itCo = cm.getComponents();
                
                int idx = 0;
                while(itCo.hasNext()){
                    Component co = itCo.next();

                    idx++;
                    coIdx.put(co.getId(), idx);
                    idxCo.put(idx, co.getId());

                    out.write("v " + idx + " " + co.getName()  + "\n");
                }

                Iterator<Dataflow> itDf = cm.getDataFlows();
                while(itDf.hasNext()){
                    Dataflow df = itDf.next();

                    String fromCoId = df.getFromComponent().getId();
                    String toCoId = df.getToComponent().getId();

                    int fromCoIdx = coIdx.get(fromCoId);
                    int toCoIdx = coIdx.get(toCoId);

                    out.write("e " + fromCoIdx + " " + toCoIdx + " "
                        + df.getFromComponent().getName() + "." + df.getFromPort().getName() + "=>"
                        + df.getToComponent().getName() + "." + df.getToPort().getName()
                        + "\n");

                }

                out.write("\n");

            }



            out.close();
        }catch(Exception e){
            e.printStackTrace();
        }

        return filePath;
    }

}
